/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package communication;

import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.os.Handler;
import android.util.Log;
import java.io.*;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * generate an object to create, stop and use a serial bluetooth connection
 * @author isen
 */
public class AndroidConnection {
    
    private UUID mUUID;
    private String address;
    private BluetoothAdapter btAdapter = null;
  private BluetoothSocket btSocket = null; 
  BufferedReader dataIn;
  BufferedWriter dataOut;
  IncomingHandler handler;
  private Thread connect;
  private Thread connected;
  boolean running = true;
  boolean tryToConnect = true;
  
  /**
   * 
   */

    //<editor-fold defaultstate="collapsed" desc=" test Constructor">
  private AndroidConnection(){
         this.mUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
        this.address = "00:24:7E:AD:9C:5F";
        this.handler = new IncomingHandler(){

            @Override
            public void handleMoveChange(String msg) {
                throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void handleReconnect() {
                throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void handleSendMsg(String string) {
                throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void handleReset() {
                throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void handleData(String substring) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
            
        };
    }
  //</editor-fold>
  /**
   * 
   * @param handler
   */
  public AndroidConnection(IncomingHandler handler){
        this.handler = handler;
         this.mUUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
        //this.address = "70:F3:95:87:30:9D";
         this.address = "00:24:7E:AD:9C:5F";
    }
    
    /**
     * 
     */
    public void close(){
        Log.w("AndroidConnection", "terminating connection");
        this.tryToConnect = false;
        resetConnection();
    }
    private void resetConnection(){
        running = false;
        
        try {
            if (dataOut!=null)dataOut.close();
            if(dataIn!=null)dataIn.close();
            if (btSocket != null) btSocket.close();
        } catch (IOException ex) {
            Logger.getLogger(AndroidConnection.class.getName()).log(Level.SEVERE, null, ex);
        }
        btSocket = null;
        btAdapter = null;
        connect = null;
        connected = null;
    }
    
    /**
     * 
     */
    public void reconnect(){
        
        if (tryToConnect == false) {
            Log.v("AndroidConnection", "won't reconnect because close() method has been called");
            return;
        } //something has specified that we should'nt try to reconnect (for example, by calling the close() method).    
        resetConnection();
        initialize();
    }
    
    /**
     * 
     */
    public void initialize(){
        running = true;
        connect = new Thread(){
        
        @Override
        public void run() {
            btAdapter = BluetoothAdapter.getDefaultAdapter();
            checkBTState();
            Log.i("BluetoothClient", "Checked bluetooth state");
            BluetoothDevice device = getRemoteDevice();
            btAdapter.cancelDiscovery();
            
               
            
            while(tryToConnect){
            try {
                Log.i("bluetoothClient.initialize()", "trying to open socket");
                btSocket = device.createRfcommSocketToServiceRecord(mUUID);
                btSocket.connect();
                Log.i("BluetoothCLient","\n...Connection established and data link opened...");
                break;
                
            } catch (IOException e) {
                Log.e("BluetoothCLient.initialize()", "socket was unable to connect: " + e.getMessage() + ".");
                
                    try {
                        Thread.sleep(2000);
                        
                    } catch (InterruptedException ex) {
                        Logger.getLogger(AndroidConnection.class.getName()).log(Level.SEVERE, null, ex);
                        return;
                    }
                    Log.w("AndroidConnection.initialize()", "retrying to connect : "+tryToConnect);
                
            }
            
            }
            if(!tryToConnect) return;
            InputStream tmpIn = null;
            OutputStream tmpOut = null;
             InputStream mmInStream;
            OutputStream mmOutStream;

            // Get the BluetoothSocket input and output streams
            try {
                tmpIn = btSocket.getInputStream();
                tmpOut = btSocket.getOutputStream();
            } catch (IOException e) {
                Log.e("BluetoothClient", "temp sockets not created", e);
            }

            mmInStream = tmpIn;
            mmOutStream = tmpOut;
            //byte[] buffer = new byte[1024];
            Log.i("Bluetooth.connected()","connected to"+btSocket.getRemoteDevice());
            /*
            try {
                // Keep listening to the InputStream while connected
                Log.i("connected", "sending message to server");
                mmOutStream.write("connected \n".getBytes());
                
            } catch (IOException ex) {
                Logger.getLogger(AndroidConnection.class.getName()).log(Level.SEVERE, null, ex);
            }
            * 
            */
            Log.i("Bluetooth.connected()", "waiting for answer...");
            dataOut = new BufferedWriter(new OutputStreamWriter(mmOutStream));
            dataIn = new BufferedReader(new InputStreamReader(mmInStream));
            running = true;
            handler.sendMessage(handler.obtainMessage(IncomingHandler.RECONNECTED));
            connected.start();
            
        }
    };
        
        connected = new Thread(){

        @Override
        public void run() {
            
            Log.i("AndroidConnection.connected", "running...");
            while (running) {
                try {
                    // Read from the InputStream
                String response = dataIn.readLine();
                //Log.i("BluetoothClient", "received:"+response);
                if(response.equalsIgnoreCase("disconnect")){
                    running = false;
                     resetConnection();
                } else{
                handler.sendMessage(handler.obtainMessage(IncomingHandler.INCOMING_BT_MSG, response));
                // Send the obtained bytes to the UI Activity
               
                }
                } catch (IOException ex) {
                    Logger.getLogger(AndroidConnection.class.getName()).log(Level.SEVERE, null, ex);
                    running = false;
                    reconnect();
                    break;
                }
               
            }
            
        }
        
    };
    
        
        connect.start();
    }
 
    
    
    /**
     * 
     * @param msg
     * @return
     */
    public boolean write(String msg) {
        if(btSocket == null|| !connected.isAlive() )return false;
        
        try {
            dataOut.write(msg+"\n");
            dataOut.flush();
        } catch (IOException ex) {
            Logger.getLogger(AndroidConnection.class.getName()).log(Level.SEVERE, null, ex);
            return false;
        }
        
        //Log.i("BluetoothConnection", "wrote:"+msg);
        
        return true;
    }
    
    
    
  private void checkBTState() {
    // Check for Bluetooth support and then check to make sure it is turned on
 
    // Emulator doesn't support Bluetooth and will return null
    if(btAdapter==null) {
      Log.e("Fatal Error", "Bluetooth Not supported. Aborting.");
    } else {
      if (btAdapter.isEnabled()) {
        Log.v("bluetoothConnection","\n...Bluetooth is enabled...");
      } else {
        btAdapter.enable();
      }
    }
  }
  
  private BluetoothDevice getRemoteDevice(){
      Set<BluetoothDevice> devices = btAdapter.getBondedDevices();
            if(devices.size()==1){
                return (BluetoothDevice) devices.toArray()[0];
            }
            
            
       Log.e("BluetoothConnection", "there were more  than 1 bluetooth device bonded");     
      return null;
  }
}
